#include <iostream>
#include <vector>
#include <unordered_map>
#include <functional>
#include <memory>
#include <cstdint>
#include <unistd.h>

using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask
{
private:
    uint64_t _id;         // 定时器任务对象id
    uint32_t _timeout;    // 定时任务超时时间
    bool _canceled;       // true表示定时任务被取消
    TaskFunc _task_cb;    // 定时任务回调函数
    ReleaseFunc _release; // 用于删除时间轮中定时任务对象信息
public:
    TimerTask(uint64_t id, uint32_t timeout, const TaskFunc &task)
        : _id(id), _timeout(timeout), _canceled(false), _task_cb(task) {}
    ~TimerTask()
    {
        if (_canceled == false)
            _task_cb();
        _release();
    }

    void Cancel() { _canceled = true; }
    void SetReleaseFunc(const ReleaseFunc &release) { _release = release; }
    int DelayTime() const { return _timeout; }
};

class TimerWheel
{
private:
    using ptrTask = std::shared_ptr<TimerTask>;
    using weakTask = std::weak_ptr<TimerTask>;
    int _capacity; // 容量
    int _tick;     // 当前槽位置

    std::unordered_map<uint64_t, weakTask> _tasks; // 定时任务对象集合
    std::vector<std::vector<ptrTask>> _wheel;      // 时间轮槽

private:
    void RemoveTimer(uint64_t id)
    {
        auto it = _tasks.find(id);
        if (it != _tasks.end())
        {
            _tasks.erase(it);
        }
    }

public:
    TimerWheel() : _capacity(60), _tick(0), _wheel(_capacity) {}

    // 添加定时任务
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &task)
    {
        ptrTask pt = std::make_shared<TimerTask>(id, delay, task);
        pt->SetReleaseFunc(std::bind(&TimerWheel::RemoveTimer, this, id));

        int pos = (_tick + delay) % _capacity;
        _wheel[pos].push_back(pt);
        _tasks[id] = weakTask(pt);
    }

    // 刷新/延时定时任务 shared_ptr再次加入时间轮, 之前的指针计数不为0不会析构
    void TimerRefresh(uint64_t id)
    {
        if (_tasks.find(id) != _tasks.end())
        {
            auto it = _tasks.find(id);
            ptrTask pt = it->second.lock(); // lock获取weak_ptr管理的对象对应的shared_ptr
            if (pt)
            {
                int delay = pt->DelayTime();
                int new_pos = (_tick + delay) % _capacity;
                _wheel[new_pos].push_back(pt);
            }
        }
    }

    // 取消定时任务
    void TimerCancel(uint64_t id)
    {
        auto it = _tasks.find(id);
        if (it != _tasks.end())
        {
            ptrTask pt = it->second.lock();
            if (pt)
                pt->Cancel();
            _tasks.erase(it);
        }
    }

    // 时间轮滴答
    void RunTimerTask()
    {
        _tick = (_tick + 1) % _capacity;
        _wheel[_tick].clear(); // 清空当前槽,释放shared_ptr,触发定时任务析构
    }
};

class Test
{
public:
    Test() { std::cout << "构造" << std::endl; }
    ~Test() { std::cout << "析构" << std::endl; }
};

void DelTest(Test *t)
{
    delete t;
}

int main()
{
    TimerWheel tw;

    Test *t = new Test();

    tw.TimerAdd(888, 5, std::bind(DelTest, t));

    for (int i = 0; i < 5; i++)
    {
        sleep(1);
        tw.TimerRefresh(888); // 刷新定时任务
        tw.RunTimerTask();    // 向后移动秒针
        std::cout << "刷新定时任务, 当前5s后销毁\n";
    }
    // tw.TimerCancel(888);
    // std::cout << "取消定时任务\n";
    while (1)
    {
        sleep(1);
        std::cout << "-------------------\n";
        tw.RunTimerTask(); // 向后移动秒针
    }
    return 0;
}